package ml.tewas.threatevaluation.inputextractor;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Map.Entry;

import ml.tewas.commondata.ThreatClassificationEnum;
import ml.tewas.threatevaluation.HiddenLayerEnum;
import ml.tewas.threatevaluation.NeuronInputTypeEnum;

/**
 * The Class WeightFileDataService.
 */
public class WeightFileDataService implements IWeightDataService {

	/** The Constant WEIGHTFILE_PATH. */
	private static final String WEIGHTFILE_PATH = "./ml/tewas/res/ThreatEvaluationWeights.txt";
//	private static final String WEIGHTFILE_PATH_TRIAL = "./ml/tewas/res/ThreatEvaluationWeightsTrial.txt";
	/** The layer map. */
private Map<HiddenLayerEnum, Map<NeuronInputTypeEnum, Float>> layerMap;
	
	/** The classification map. */
	private Map<ThreatClassificationEnum, Map<HiddenLayerEnum, Float>> classificationMap;

	/**
	 * Instantiates a new weight file data service.
	 */
	public WeightFileDataService() {
		layerMap = new HashMap<HiddenLayerEnum, Map<NeuronInputTypeEnum, Float>>();
		classificationMap = new HashMap<ThreatClassificationEnum, Map<HiddenLayerEnum, Float>>();
		readThreatEvaluationWeights();
	}

	/**
	 * Read threat evaluation weights.
	 */
	private void readThreatEvaluationWeights() {
		BufferedReader br = null;
		String line = null;
		try {
			File f = new File(WEIGHTFILE_PATH);
			br = new BufferedReader(new FileReader(f));
	
			// Read the HiddenLayerEnum Part
			for (int i = 0; i < 2; i++) {
				HiddenLayerEnum hiddenLayerEnum = HiddenLayerEnum.valueOf(br
						.readLine());
				Map<NeuronInputTypeEnum, Float> map = new HashMap<NeuronInputTypeEnum, Float>();
				for (int j = 0; j < 4; j++) {
					line = br.readLine();
					StringTokenizer tokenizer = new StringTokenizer(line);
					NeuronInputTypeEnum neuron = NeuronInputTypeEnum
							.valueOf(tokenizer.nextToken("	"));
					float value = Float.parseFloat(tokenizer.nextToken("	"));
					map.put(neuron, value);
				}
				layerMap.put(hiddenLayerEnum, map);
			}
			// Read the other Part
			for (int i = 0; i < 4; i++) {
				ThreatClassificationEnum classificationEnum = ThreatClassificationEnum
						.valueOf(br.readLine());
				Map<HiddenLayerEnum, Float> map = new HashMap<HiddenLayerEnum, Float>();
				for (int j = 0; j < 2; j++) {
					line = br.readLine();
					StringTokenizer tokenizer = new StringTokenizer(line);
					HiddenLayerEnum neuron = HiddenLayerEnum.valueOf(tokenizer
							.nextToken("	"));
					float value = Float.parseFloat(tokenizer.nextToken("	"));
					map.put(neuron, value);
				}
				classificationMap.put(classificationEnum, map);
			}

		} catch (IOException e) {
			System.out.println(e.getMessage());
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	/**
	 * Write threat evaluation weights.
	 */
	private void writeThreatEvaluationWeights() {
		BufferedWriter bw = null;
		try {
			File f = new File(WEIGHTFILE_PATH);
			bw = new BufferedWriter(new FileWriter(f));
			// write the HiddenLayerEnum Part
			Set<Entry<HiddenLayerEnum, Map<NeuronInputTypeEnum, Float>>> layerEntries = layerMap
					.entrySet();
			Iterator<Entry<HiddenLayerEnum, Map<NeuronInputTypeEnum, Float>>> layerIter = layerEntries
					.iterator();
			while (layerIter.hasNext()) {
				Entry<HiddenLayerEnum, Map<NeuronInputTypeEnum, Float>> entry = layerIter
						.next();
				bw.write(entry.getKey() + "\n");
				Map<NeuronInputTypeEnum, Float> map = entry.getValue();
				Set<Entry<NeuronInputTypeEnum, Float>> mapEntries = map
						.entrySet();
				Iterator<Entry<NeuronInputTypeEnum, Float>> mapIter = mapEntries
						.iterator();
				while (mapIter.hasNext()) {
					Entry<NeuronInputTypeEnum, Float> neuron = mapIter.next();
					bw.write(neuron.getKey() + "	" + neuron.getValue() + "\n");
				}
			}
			// write the other Part
			Set<Entry<ThreatClassificationEnum, Map<HiddenLayerEnum, Float>>> classificationEntries = classificationMap
					.entrySet();
			Iterator<Entry<ThreatClassificationEnum, Map<HiddenLayerEnum, Float>>> classificationIter = classificationEntries
					.iterator();
			while (classificationIter.hasNext()) {
				Entry<ThreatClassificationEnum, Map<HiddenLayerEnum, Float>> entry = classificationIter
						.next();
				bw.write(entry.getKey() + "\n");
				Map<HiddenLayerEnum, Float> map = entry.getValue();
				Set<Entry<HiddenLayerEnum, Float>> mapEntries = map.entrySet();
				Iterator<Entry<HiddenLayerEnum, Float>> mapIter = mapEntries
						.iterator();
				while (mapIter.hasNext()) {
					Entry<HiddenLayerEnum, Float> neuron = mapIter.next();
					bw.write(neuron.getKey() + "	" + neuron.getValue() + "\n");
				}
			}
		} catch (IOException e) {
			System.out.println(e.getMessage());
		} finally {
			try {
				bw.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	/* (non-Javadoc)
	 * @see ml.tewas.threatevaluation.inputextractor.IWeightDataService#readWeightsForHiddenLayer(ml.tewas.threatevaluation.HiddenLayerEnum)
	 */
	public Map<NeuronInputTypeEnum, Float> readWeightsForHiddenLayer(
			HiddenLayerEnum layer) {

		return layerMap.get(layer);
	}

	/* (non-Javadoc)
	 * @see ml.tewas.threatevaluation.inputextractor.IWeightDataService#readWeightsForOutputNeuron(ml.tewas.commondata.ThreatClassificationEnum)
	 */
	public Map<HiddenLayerEnum, Float> readWeightsForOutputNeuron(
			ThreatClassificationEnum classification) {

		return classificationMap.get(classification);
	}

	/* (non-Javadoc)
	 * @see ml.tewas.threatevaluation.inputextractor.IWeightDataService#writeWeightsForHiddenLayer(ml.tewas.threatevaluation.HiddenLayerEnum, java.util.Map)
	 */
	public void writeWeightsForHiddenLayer(HiddenLayerEnum layer,
			Map<NeuronInputTypeEnum, Float> map) {
		layerMap.put(layer, map);
	}

	/* (non-Javadoc)
	 * @see ml.tewas.threatevaluation.inputextractor.IWeightDataService#writeWeightsForOutputNeuron(ml.tewas.commondata.ThreatClassificationEnum, java.util.Map)
	 */
	public void writeWeightsForOutputNeuron(
			ThreatClassificationEnum classification,
			Map<HiddenLayerEnum, Float> map) {
		classificationMap.put(classification, map);

	}
	
	/* (non-Javadoc)
	 * @see ml.tewas.threatevaluation.inputextractor.IWeightDataService#saveService()
	 */
	public void saveService() {
		writeThreatEvaluationWeights();
	}

}

